package sdk

import (
	"context"
	"encoding/base64"
	"fmt"
	"gim-server/config"
	"github.com/tencentyun/cos-go-sdk-v5"
	"net/http"
	"net/url"
	"sync"
	"time"
)

var (
	cosClient *cos.Client
	cosOnce   sync.Once
)

type CosAuditResult struct {
	Flag  int    `json:"flag"`
	Label string `json:"label"`
	Score int    `json:"score"`
	Key   string `json:"key"`
}

func CosOrgDomain() string {
	cfg := config.GetCfg()
	return fmt.Sprintf("https://%v.cos.%v.myqcloud.com", cfg.CosBucket, cfg.CosRegion)
}

func CosClient() *cos.Client {
	cosOnce.Do(func() {
		cfg := config.GetCfg()
		bu, err := url.Parse(fmt.Sprintf("https://%v.cos.%v.myqcloud.com", cfg.CosBucket, cfg.CosRegion))
		if err != nil {
			panic("初始化COS_CLIENT失败")
		}
		su, err := url.Parse(fmt.Sprintf("https://cos.%v.myqcloud.com", cfg.CosRegion))
		if err != nil {
			panic("初始化COS_CLIENT失败")
		}
		ci, err := url.Parse(fmt.Sprintf("https://%v.ci.%v.myqcloud.com", cfg.CosBucket, cfg.CosRegion))
		if err != nil {
			panic("初始化COS_CLIENT失败")
		}
		b := &cos.BaseURL{BucketURL: bu, ServiceURL: su, CIURL: ci}
		cosClient = cos.NewClient(b, &http.Client{
			Transport: &cos.AuthorizationTransport{
				SecretID:  cfg.CosSecretId,
				SecretKey: cfg.CosSecretKey,
			},
		})
	})
	return cosClient
}

func GenUploadUrl(key string) (string, error) {
	ctx := context.Background()
	cfg := config.GetCfg()
	url, err := CosClient().Object.GetPresignedURL(ctx, http.MethodPut, key, cfg.CosSecretId, cfg.CosSecretKey, time.Minute, nil)
	if err != nil {
		return "", err
	}
	return url.String(), nil
}

// CosAuditText 文本审核
func CosAuditText(txt string) (*CosAuditResult, error) {
	opt := &cos.PutTextAuditingJobOptions{
		InputContent: base64.StdEncoding.EncodeToString([]byte(txt)),
		Conf: &cos.TextAuditingJobConf{
			DetectType: "Porn,Ads,Illegal,Abuse,Politics,Terrorism",
			BizType:    config.GetCfg().CosTextAuditBizType,
		},
	}
	res, _, err := CosClient().CI.PutTextAuditingJob(context.Background(), opt)
	if err != nil {
		return nil, err
	}
	detail := res.JobsDetail
	fmt.Printf("%+v\n", detail)
	auditRes := new(CosAuditResult)
	auditRes.Key = txt
	auditRes.Flag = detail.Result
	auditRes.Label = detail.Label
	auditRes.Score = detail.Result
	if detail.Result != 0 && len(detail.Section) > 0 {
		si := detail.Section[0]
		if si.PornInfo != nil && si.PornInfo.HitFlag != 0 {
			auditRes.Label = si.PornInfo.Keywords
			auditRes.Score = si.PornInfo.Score
		}
		if si.TerrorismInfo != nil && si.TerrorismInfo.HitFlag != 0 {
			auditRes.Label = si.TerrorismInfo.Keywords
			auditRes.Score = si.TerrorismInfo.Score
		}
		if si.PoliticsInfo != nil && si.PoliticsInfo.HitFlag != 0 {
			auditRes.Label = si.PoliticsInfo.Keywords
			auditRes.Score = si.PoliticsInfo.Score
		}
		if si.AdsInfo != nil && si.AdsInfo.HitFlag != 0 {
			auditRes.Label = si.AdsInfo.Keywords
			auditRes.Score = si.AdsInfo.Score
		}
		if si.IllegalInfo != nil && si.IllegalInfo.HitFlag != 0 {
			auditRes.Label = si.IllegalInfo.Keywords
			auditRes.Score = si.IllegalInfo.Score
		}
	}
	return auditRes, nil
}

type AuditImageResult struct {
	Results []*CosAuditResult `json:"results"`
	Flag    int               `json:"flag"`
	Label   string            `json:"label"`
	Score   int               `json:"score"`
	Key     string            `json:"key"`
}

// CosAuditImage 图片审核
func CosAuditImage(imgs []string) (*AuditImageResult, error) {
	opt := &cos.BatchImageAuditingOptions{
		Input: func() []cos.ImageAuditingInputOptions {
			lst := make([]cos.ImageAuditingInputOptions, 0)
			for _, img := range imgs {
				lst = append(lst, cos.ImageAuditingInputOptions{
					DataId: base64.StdEncoding.EncodeToString([]byte(img)),
					Object: img,
				})
			}
			return lst
		}(),
		Conf: &cos.ImageAuditingJobConf{
			DetectType: "Porn,Ads,Politics,Terrorism",
			BizType:    config.GetCfg().CosImageAuditBizType,
		},
	}
	fmt.Printf("图片审核BizType：%s\n", config.GetCfg().CosImageAuditBizType)
	res, _, err := CosClient().CI.BatchImageAuditing(context.Background(), opt)
	if err != nil {
		return nil, err
	}
	dto := &AuditImageResult{
		Results: nil,
		Flag:    0,
		Label:   "Normal",
		Score:   0,
		Key:     "",
	}
	auditResults := make([]*CosAuditResult, 0)
	for _, detail := range res.JobsDetail {
		auditRes := new(CosAuditResult)
		key, _ := base64.StdEncoding.DecodeString(detail.DataId)
		auditRes.Key = string(key)
		auditRes.Flag = detail.Result
		auditRes.Label = detail.Label
		auditRes.Score = detail.Score
		auditResults = append(auditResults, auditRes)
		if detail.Result != 0 {
			dto.Key = string(key)
			dto.Flag = detail.Result
			dto.Label = detail.Label
			dto.Score = detail.Score
		}
	}
	dto.Results = auditResults
	return dto, nil
}
